﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace KxApp.Utils
{
    public class StringToIntMapper
    {
        public static string Err { get; set; } = string.Empty;

        // 字母到数字的映射
        private static readonly Dictionary<char, int> charToValue = new Dictionary<char, int>
        {
            { 'C', 0 },
            { 'D', 1 },
            { 'V', 2 },
        };

        // 数字到字母的映射（用于反向转换）
        private static readonly Dictionary<int, char> valueToChar = new Dictionary<int, char>
        {
            { 0, 'C' },
            { 1, 'D' },
            { 2, 'V' },
        };

        // 将字符串映射到整数
        public static int StringToInt(string s)
        {
            if (string.IsNullOrEmpty(s) || s.Length > 6)
            {
                Err = "String length must be between 1 and 6.";
                return 0;
            }
            //throw new ArgumentException("String length must be between 1 and 6.");

            int length = s.Length;
            /*
             不同长度的字符串必须映射到不重叠的整数范围，例如：
            长度1的字符串：0 到 2（共 3 个）。
            长度2的字符串：3 到 11（共 9 个）。
            长度3的字符串：12 到 38（共 27 个）。
            长度4: 映射范围：39 到 116（共 81 个）
            长度5 : 映射范围：120 到 359（共 243 个）
            长度6 : 映射范围：363 到 1091（共 729 个）
            因此，长度为 L 的字符串的整数范围应从 offset(L) 开始，其中 offset(L) 是前 L-1 长度的所有字符串的总数。
            offsetL = (3^L -3)/2
            3, 12, 39
             */
            int offset = (int)((Math.Pow(3, length) - 3) / 2);
            int value = 0;

            for (int i = 0; i < length; i++)
            {
                char c = s[i];
                if (!charToValue.ContainsKey(c))
                {
                    //throw new ArgumentException(
                    //    $"Invalid character '{c}'. Only 'C', 'D', 'V' are allowed."
                    //);
                    Err = $"Invalid character '{c}'. Only 'C', 'D', 'V' are allowed.";
                }

                value = value * 3 + charToValue[c];
            }

            return offset + value;
        }

        // 将整数映射回字符串
        public static string IntToString(int num)
        {
            if (num < 0)
            {
                Err = "Number must be non-negative.";
            }
                //throw new ArgumentException("Number must be non-negative.");

            // 确定长度
            int length = 1;
            while (true)
            {
                int maxForLength = (int)((Math.Pow(3, length + 1) - 3) / 2 - 1);
                if (num <= maxForLength)
                    break;
                length++;
                if (length > 6)
                {
                    Err = "Number is too large for any string of length 1-6";
    //                throw new ArgumentException(
    //"Number is too large for any string of length 1-6."
//);
                }

            }

            int offset = (int)((Math.Pow(3, length) - 3) / 2);
            int value = num - offset;

            if (value < 0 || value >= (int)Math.Pow(3, length))
            {
                Err = "Number does not correspond to any valid string.";
                //throw new ArgumentException("Number does not correspond to any valid string.");
            }


            char[] chars = new char[length];
            for (int i = length - 1; i >= 0; i--)
            {
                chars[i] = valueToChar[value % 3];
                value /= 3;
            }

            return new string(chars);
        }
    }
}
